import json

import pytz
import requests
from aiogram import Bot, Dispatcher, types, F
import asyncio
from asyncio import Semaphore
import aiofiles
import io
import logging
import datetime
import time
from asgiref.sync import sync_to_async, async_to_sync
from icecream import ic
from numpy import number
# from models import get_users, init, get_user, create_user, create_conteiner, get_first_conteiner, ImagesConteiner, get_conteiner, StatusConteiner
from aiogram.filters import CommandStart, Command
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove, Message, ContentType, InputMediaPhoto, InputFile
from aiogram.fsm.context import FSMContext
# from app.keyboards import main_kb, inspection_kb, completion, data_conteiner, start_kb
# from utilites.utilits_bot import coincidence
from aiogram import Router
from passlib.hash import bcrypt

import http_rest
from app.keyboards import users, tech_actions, the_start, auth_inline, user_list_kb, for_start
from form.forms import Auth
# from form.forms import Form, Stat

from model.models import create_user, User, get_user_db
from utilites.DecoratorTheard import threaClass
from utilites.bot_util import curent_date, verify_tg_user

router = Router()
semaphore = Semaphore(5)
USER = ' '.join(users)
TEMP_AUTH = []
task = None
us_id = []
AUTHORS = {}



async def jason_save(file=None, data: dict=None, open_file: bool = False):
    async with aiofiles.open(f"{file}.json", mode="w" if data else "r", encoding="utf-8") as f:
        if data:
            await f.write(json.dumps(data, ensure_ascii=False, indent=4))
        else:
            try:
                data = json.loads(await f.read())
            except json.decoder.JSONDecodeError:
                posted_gps = asyncio.create_task(process_bac(new_jur=True))
                await posted_gps
                data = await jason_save(file='REF_JURNAL', open_file=True)
            return data


async def load_bottons_data(jt_number):
    ref_key = jt_number['Ref_Key']
    filter = ''
    text_request = {
        "filter": 'Ref_Key eq guid`' + ref_key + '` and startswith (МестоРазмещения,`' + filter + '`) eq true',
        "expand": 'Контейнер',
        'orderby': 'LineNumber'}
    request = await http_rest.send_odata_get("Document_ЖурналОбходовРефов_Контейнеры",
                                       text_request)
    data = request.json()
    await jason_save(file='CONTEINERS_RF', data=data['value'])


async def json_to_dict(json_obj):
    posted_gps = {}
    count = len([item for item in json_obj['#value']['row'] if item[10]['#value'] != "0001-01-01T00:00:00"])

    posted_gps['Дата'] = json_obj['#value']['row'][0][1]['#value']
    posted_gps['Номер'] = json_obj['#value']['row'][0][0]['#value']
    posted_gps['колличество'] = json_obj['#value']['row'][-1][3]['#value']
    posted_gps['осмотренные'] = count

    for i, item in enumerate(json_obj['#value']['row'], start=1):


        list_gps = item[5]['#value'].replace('  ', ' ').split('; ')
        key = list_gps[0] + ' ' + list_gps[1] if len(list_gps) == 3 else list_gps[0]
        if key not in posted_gps:
            posted_gps[key] = {}  # Если ключа нет в словаре, создаем пустой список

        # Добавляем новый словарь в список, соответствующий ключу
        posted_gps[key][item[12]['#value']] = {
            'num': i,
            'doc_num': item[0]['#value'],
            'ContNum': item[12]['#value'],
            'Контейнер_Key': item[4]['#value'],
            'gps': item[5]['#value'],
            'LineNumber': item[3]['#value'],
            'ФактическаяT': item[7]['#value'],
            'НормативнаяT': item[6]['#value'],
            'Ref_Key': item[2]['#value'],
            'Cargo': item[9]['#value'],
            'ДатаОсмотра': item[10]['#value'],
            'Lasterr': item[8]['#value'] if item[8]['#value'] else 'НЕТ'

        }
    ic(posted_gps)
    return posted_gps


async def create_new_jurnal(authors):
    long_text = {
        "Сотрудник_Key": authors,
        "Примечание": "Created by @ReffApp",
        "РегламентноеСоздание": "true"}

    update_req = await http_rest.send_odata_post('Document_ЖурналОбходовРефов', long_text)

    await asyncio.gather(asyncio.create_task(http_rest.fillRJ(update_req.json()['Ref_Key'])),
                                      asyncio.create_task(http_rest.send_odata_get("Document_ЖурналОбходовРефов",
                                                         {"filter": "Ref_Key eq guid`" + update_req.json()['Ref_Key']
                                                                    + "`"})))

    new = await http_rest.jurnal_list()
    new = await json_to_dict(new.json())
    await jason_save(file='REF_JURNAL', data=new, open_file=False)
    return new


async def process_bac(authors=None, update_jur=False, new_jur=False):
    authors = '60395635-f4b7-11e9-82b6-000c298971da'
    ic('process_bac сработал 2')
    new = await http_rest.jurnal_list()
    ic('process_bac сработал 2-1')
    new = await json_to_dict(new.json())

    ic('process_bac сработал 3')
    date_string = new['Дата']
    date_time = pytz.timezone('Europe/Moscow').localize(datetime.datetime.fromisoformat(date_string))

    # Текущее время с учетом часового пояса
    current_datetime = datetime.datetime.now(pytz.timezone('Europe/Moscow'))

    time_difference = current_datetime - date_time
    if update_jur:
        ic('process_bac сработал 1')
        if time_difference < datetime.timedelta(hours=4):
            REF_JURNAL = new
            await jason_save(file='REF_JURNAL', data=new, open_file=False)
        else:
            REF_JURNAL = await create_new_jurnal(authors)
    elif new_jur:
        REF_JURNAL = await create_new_jurnal(authors)
    else:
        REF_JURNAL = await create_new_jurnal(authors)
    return REF_JURNAL


async def keyboard():
    users = [user['name'] for user in await User.all().values('id', 'name')]
    auth_kb = ReplyKeyboardMarkup(
        keyboard=[
            [
                KeyboardButton(text=user) for user in users
            ]
        ],
        resize_keyboard=True,
        one_time_keyboard=True,
        input_field_placeholder="Выберите действие",
        selective=True
    )

    return auth_kb


@router.message(CommandStart())
async def start_message(message: Message, state: FSMContext):
    global task
    await state.clear()
    await message.delete()
    UserId = str(message.from_user.id)
    async with semaphore:
        request = await verify_tg_user(UserId)
    #text_request = {
        #"filter": "ИдентификаторТ eq `" + UserId + "` and Контрагент_Type eq `StandardODATA.Catalog_Сотрудники`"}
    #request = await http_rest.send_odata_get("InformationRegister_ТелеграмПодписки", text_request)
    data = request.json()
    if not data['value']:
        await message.bot.send_message(453994951, f'Запрос на подключение к боту {message.from_user.id} имя {message.from_user.first_name}')
        await message.answer(f'Передайте ваш ID администратору, {message.from_user.id}')
    else:
        text_request = {"select": "Ref_Key,ПолноеНаименование,ПарольАвторизации",
                        "filter": "ДолжностьСотрудника_Key eq guid`563e4aa7-5aa0-435e-9ded-06d410d8865b` and DeletionMark eq false"}
        request = await http_rest.send_odata_get("Catalog_Сотрудники", text_request)
        data = request.json()


        user_dict = {value['ПолноеНаименование']: {'password': value['ПарольАвторизации'], 'id': value['Ref_Key']} for value in data['value']}
        await state.update_data(user_dict)
        auth_kb = await user_list_kb(data)
        await state.set_state(Auth.login)
        delete_message = await message.answer('Выполните\nавторизацию', reply_markup=ReplyKeyboardRemove())
        await asyncio.sleep(1)
        await delete_message.delete()
        await message.answer(f'Выберете пользователя', reply_markup=auth_kb)


@router.callback_query(F.data == 'auth')
async def auth_callback(callback_query: types.Update, state: FSMContext):
    await state.set_state(Auth.login)
    global us_id
    auth_kb = await keyboard()
    if callback_query.data == 'auth':
        await callback_query.bot.send_message(453994951, f'Требуется добавить пользователя {callback_query.from_user.id} имя {callback_query.from_user.first_name}',reply_markup=for_start)
        await state.clear()


@router.callback_query(F.data == 'start')
async def start_callback(callback_query: types.Update, state: FSMContext):
    await state.set_state(Auth.login)
    global us_id
    us_id.append(callback_query.from_user.id)
    await state.set_state(Auth.login)
    await callback_query.message.answer('........................', reply_markup=for_start)


# Фильтр по пользовотелям
async def is_user_message(message: Message, state: FSMContext) -> bool:
    users = await state.get_data()
    return True if message.text in users.keys() else False


async def not_is_user_message(message: Message, state: FSMContext) -> bool:
    users = await state.get_data()
    return False if message.text in users.keys() else True


# @router.message(Auth.login, is_user_message)
# async def get_user(message: Message, state: FSMContext):
#     user = []
#     # Установка состояния пользователя
#     await state.update_data({'login_user': message.text})
#     await state.set_state(Auth.password)
#     password = await state.get_data()
#     if not await get_user_db(message.text):
#         await create_user(name=message.text, password=password[message.text])
#     # Отправка сообщения с приглашением ввода пароля
#     await message.answer('Пожалуйста, введите свой пароль:')


@router.callback_query(F.data.startswith('Ref-Key'))
async def get_user(callback_query: types.Update, state: FSMContext):
    # callback_query.data
    data = await state.get_data()
    for key, value in data.items():

        if value['id'] == callback_query.data.split('_')[1]:
            await state.update_data({'login_user': key})
            break
    await state.set_state(Auth.password)
    await callback_query.message.delete()
    # Отправка сообщения с приглашением ввода пароля
    bot_message = await callback_query.message.answer('Пожалуйста, введите свой пароль:')
    await state.update_data({'message_id': bot_message.message_id})


@router.message(Auth.login, not_is_user_message)
async def get_user(message: Message, state: FSMContext):
    global task
    if not not task:
        task.cancel()
    await message.delete()
    await state.clear()
    await state.set_state(Auth.login)
    auth_kb = await keyboard()
    await message.answer(f'__________________', reply_markup=for_start)


async def delitting_message(bot_message):
    await asyncio.sleep(5)



@router.message(Auth.password)
async def get_password(message: Message, state: FSMContext):
    global task
    login_data = await state.get_data()
    id_tg_us = message.from_user.id
    login = login_data.get('login_user')
    hashed_password = message.text
    if hashed_password == login_data[login]['password']:
        await message.delete()
        global AUTHORS
        AUTHORS[id_tg_us] = login_data[login]['id']
        bot_message_id = login_data['message_id']
        await message.bot.delete_message(message.chat.id, bot_message_id)
        await message.bot.send_message(message.chat.id, f'Авторизация прошла успешно!', reply_markup=tech_actions)

        await state.clear()
    else:
        await state.set_state(Auth.login)
        await message.answer('Неверный логин или пароль\nДля востановления пароля обратитесь к администратору', reply_markup=for_start)


#@router.message(F.text == 'Закрыть смену')
#async def finish_work(message: Message, state: FSMContext):
    # global task
    # task.cancel()
    #await message.delete()
    #await state.clear()
    #await state.set_state(Auth.login)
    #await message.answer('Завершение смены', reply_markup=for_start)


@router.callback_query(F.data == 'the_end')
async def finish_work(callback_wuery: types.CallbackQuery, state: FSMContext):
    # global task
    # task.cancel()
    await callback_wuery.message.delete()
    await state.clear()
    await state.set_state(Auth.login)
    currrent_date_time = await curent_date()
    bot_message = await callback_wuery.message.answer(f'Смена завершена {currrent_date_time}', reply_markup=for_start)

